package com.sky.chapter3.bq;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.function.Consumer;

/**
 * @author : wushikai
 * <p>
 * date : 2022-07-13
 * 生产者与消费者案例，一个生产者和多个消费者。
 */
public class BlockQueueDemo {


    /**
     * 生产者
     */
    private static class Producer implements Runnable {

        private BlockingQueue<Integer> blockingQueue;

        Producer(BlockingQueue blockingQueue) {
            this.blockingQueue = blockingQueue;
        }

        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(200);
                    blockingQueue.put(i);     //往队列增加一个对象，如果没有空间，则会阻塞改线程，直到有空间.
                    System.out.println("生产者产品了产品" + i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 消费者
     */
    private static class Consumer implements Runnable {

        private BlockingQueue<Integer> blockingQueue = new LinkedBlockingDeque<Integer>();

        Consumer(BlockingQueue blockingQueue) {
            this.blockingQueue = blockingQueue;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    String name = Thread.currentThread().getName();
                    Integer queueData = blockingQueue.take(); //取出队头元素,if队列中没有数据,则会阻塞该线程直到有数据
                    System.out.println("消费者" + name + "消费了产品" + queueData);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 一个生产者对应多个消费者，采用BlockQueue作为缓冲区
     */
    public static void main(String[] args) {
        BlockingQueue<Integer> blockingQueue = new LinkedBlockingDeque<>();
        Producer producer = new Producer(blockingQueue);
        Consumer consumer = new Consumer(blockingQueue);

        new Thread(producer).start();
        new Thread(consumer).start();

    }

}


